package com.bml.architect.data.writer;

import com.alibaba.cloud.nacos.NacosConfigManager;
import com.alibaba.cloud.sentinel.SentinelProperties;
import com.alibaba.cloud.sentinel.datasource.config.DataSourcePropertiesConfiguration;
import com.alibaba.csp.sentinel.datasource.Converter;
import com.alibaba.csp.sentinel.datasource.WritableDataSource;
import com.alibaba.csp.sentinel.init.InitFunc;
import com.alibaba.csp.sentinel.slots.block.authority.AuthorityRule;
import com.alibaba.csp.sentinel.slots.block.degrade.DegradeRule;
import com.alibaba.csp.sentinel.slots.block.flow.FlowRule;
import com.alibaba.csp.sentinel.slots.system.SystemRule;
import com.alibaba.csp.sentinel.transport.util.WritableDataSourceRegistry;
import com.alibaba.fastjson.JSON;
import com.alibaba.nacos.api.config.ConfigService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.context.event.ApplicationReadyEvent;
import org.springframework.context.ApplicationListener;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import java.util.List;

/**
 * @author: baiml
 * @Title: NacosDataSourceInit
 * @ProjectName: 中台技术平台
 * @Depart 中台研发部
 * @Description:
 * @date: 2021/5/8 18:29
 */
@Component
public class NacosDataSourceInit implements ApplicationListener<ApplicationReadyEvent> {

    @Autowired
    private SentinelProperties sentinelProperties;


    @Autowired
    private NacosConfigManager nacosConfigManager;

    private ConfigService configService;

    @Override
    public void onApplicationEvent(ApplicationReadyEvent applicationReadyEvent) {


        sentinelProperties.getDatasource().forEach(this::handler);


    }


    /**
     * @param s             流控的名称就是在yaml中配置的datasource名称
     * @param configuration
     */
    private void handler(String s, DataSourcePropertiesConfiguration configuration) {
        switch (configuration.getNacos().getRuleType()) {
            case FLOW:
                dealFlowRule(configuration);
                break;
            case SYSTEM:
                dealSystemRule(configuration);
                break;
            case DEGRADE:
                dealDegradeRule(configuration);
                break;
            case GW_FLOW:
                break;
            case AUTHORITY:
                dealAuthRule(configuration);
                break;
            case PARAM_FLOW:
                break;
            case GW_API_GROUP:
                break;
        }
    }


    /**
     * 流控
     *
     * @param configuration
     */
    private void dealFlowRule(DataSourcePropertiesConfiguration configuration) {
        WriteDataSourceWrapper<List<FlowRule>> wrapper =
                new WriteDataSourceWrapper<>(configService, RuleConvert.flowRule, configuration.getNacos());
        WritableDataSource<List<FlowRule>> writableDataSource = new NacosWriteDataSource<>(wrapper);
        WritableDataSourceRegistry.registerFlowDataSource(writableDataSource);
    }

    /**
     * 降级
     *
     * @param configuration
     */
    private void dealDegradeRule(DataSourcePropertiesConfiguration configuration) {

        WriteDataSourceWrapper<List<DegradeRule>> wrapper =
                new WriteDataSourceWrapper<>(configService, RuleConvert.degradeRule, configuration.getNacos());
        WritableDataSource<List<DegradeRule>> writableDataSource = new NacosWriteDataSource<>(wrapper);
        WritableDataSourceRegistry.registerDegradeDataSource(writableDataSource);
    }

    /**
     * 系统规则
     *
     * @param configuration
     */
    private void dealSystemRule(DataSourcePropertiesConfiguration configuration) {

        WriteDataSourceWrapper<List<SystemRule>> wrapper =
                new WriteDataSourceWrapper<>(configService, RuleConvert.systemRule, configuration.getNacos());
        WritableDataSource<List<SystemRule>> writableDataSource = new NacosWriteDataSource<>(wrapper);
        WritableDataSourceRegistry.registerSystemDataSource(writableDataSource);
    }

    private void dealAuthRule(DataSourcePropertiesConfiguration configuration) {

        WriteDataSourceWrapper<List<AuthorityRule>> wrapper =
                new WriteDataSourceWrapper<>(configService, RuleConvert.authRule, configuration.getNacos());
        WritableDataSource<List<AuthorityRule>> writableDataSource = new NacosWriteDataSource<>(wrapper);
        WritableDataSourceRegistry.registerAuthorityDataSource(writableDataSource);
    }


    @PostConstruct
    private void init() {
        this.configService = nacosConfigManager.getConfigService();
    }
}
